#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <direct.h>
#include <errno.h>

// 引入嵌入的二进制数据
#include "embed_dll.h"
#include "embed_exe.h"

// --------------------------
// 获取self_extract.exe所在的目录（当前程序目录）
// --------------------------
char* get_exe_dir() {
    static char exe_dir[MAX_PATH] = {0};
    char exe_path[MAX_PATH] = {0};

    // 获取当前程序（self_extract.exe）的完整路径
    if (GetModuleFileNameA(NULL, exe_path, MAX_PATH) == 0) {
        fprintf(stderr, "警告：无法获取程序路径，使用当前工作目录\n");
        _getcwd(exe_dir, MAX_PATH);
        return exe_dir;
    }

    // 从完整路径中提取目录部分（去掉文件名）
    char* last_slash = strrchr(exe_path, '\\');
    if (last_slash) {
        *last_slash = '\0'; // 截断文件名，保留目录
        strncpy(exe_dir, exe_path, MAX_PATH - 1);
    } else {
        // 找不到目录分隔符，使用当前工作目录
        _getcwd(exe_dir, MAX_PATH);
    }

    printf("程序所在目录：%s\n", exe_dir);
    return exe_dir;
}

// --------------------------
// 将二进制数据写入当前目录的文件
// --------------------------
int write_bin_to_current_dir(const unsigned char* data, unsigned int size, const char* filename) {
    char full_path[MAX_PATH] = {0};
    char* exe_dir = get_exe_dir();
    
    // 构造完整路径：程序目录 + 文件名
    snprintf(full_path, MAX_PATH, "%s\\%s", exe_dir, filename);

    FILE* f = fopen(full_path, "wb");
    if (!f) {
        fprintf(stderr, "提取文件失败：%s（%s）\n", full_path, strerror(errno));
        return 0;
    }

    size_t written = fwrite(data, 1, size, f);
    fclose(f);

    if (written != size) {
        fprintf(stderr, "写入文件不完整：%s\n", full_path);
        DeleteFileA(full_path);
        return 0;
    }

    printf("成功提取：%s\n", full_path);
    return 1;
}

// --------------------------
// 启动主程序（在程序目录运行，传递原始参数）
// --------------------------
int run_main_exe() {
    char* exe_dir = get_exe_dir();
    char exe_path[MAX_PATH] = {0};
    snprintf(exe_path, MAX_PATH, "%s\\unzip_tool.exe", exe_dir);

    // 构造命令行：unzip_tool.exe <压缩包路径> <输出目录>
    // 注意：argv[0]是self_extract.exe，argv[1]是压缩包，argv[2]是输出目录
    char cmd_line[MAX_PATH * 4] = {0};
    snprintf(cmd_line, sizeof(cmd_line), "\"%s\"", exe_path); // 主程序路径

    // 追加用户传入的参数（压缩包路径和输出目录）
    for (int i = 1; i < __argc; i++) {
        strncat(cmd_line, " \"", sizeof(cmd_line) - strlen(cmd_line) - 1);
        strncat(cmd_line, __argv[i], sizeof(cmd_line) - strlen(cmd_line) - 1);
        strncat(cmd_line, "\"", sizeof(cmd_line) - strlen(cmd_line) - 1);
    }

    printf("\n执行解压命令：%s\n", cmd_line);

    STARTUPINFOA si = {0};
    PROCESS_INFORMATION pi = {0};
    si.cb = sizeof(STARTUPINFOA);

    // 在程序目录启动主程序（确保相对路径正确解析）
    if (!CreateProcessA(
        NULL,           // 从命令行获取程序路径
        cmd_line,       // 完整命令行
        NULL,           // 进程安全属性
        NULL,           // 线程安全属性
        FALSE,          // 不继承句柄
        0,              // 创建标志
        NULL,           // 环境变量
        exe_dir,        // 工作目录：程序所在目录
        &si,
        &pi
    )) {
        fprintf(stderr, "启动解压工具失败（错误码：%lu）\n", GetLastError());
        return 0;
    }

    // 等待解压完成
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

    return 1;
}

// --------------------------
// 清理临时提取的文件（保留用户输出目录）
// --------------------------
void clean_temp_files() {
    char* exe_dir = get_exe_dir();
    char dll_path[MAX_PATH] = {0};
    char exe_path[MAX_PATH] = {0};

    snprintf(dll_path, MAX_PATH, "%s\\unzip.dll", exe_dir);
    snprintf(exe_path, MAX_PATH, "%s\\unzip_tool.exe", exe_dir);

    // 删除提取的DLL和EXE
    if (DeleteFileA(dll_path)) {
        printf("已删除临时文件：%s\n", dll_path);
    }
    if (DeleteFileA(exe_path)) {
        printf("已删除临时文件：%s\n", exe_path);
    }
}

// --------------------------
// 主函数
// --------------------------
int main(int argc, char* argv[]) {
    printf("=== 简易自解压工具 ===\n");
    printf("======================\n");

    // 检查参数
    if (argc < 3) {
        fprintf(stderr, "用法：%s <压缩包路径> <输出目录>\n", argv[0]);
        fprintf(stderr, "示例：%s upx-5.0.2-win64.zip urmom\n", argv[0]);
        return 1;
    }

    // 1. 提取unzip.dll和unzip_tool.exe到当前程序目录
    printf("正在提取必要文件...\n");
    if (!write_bin_to_current_dir(dll_data, dll_data_size, "unzip.dll")) {
        return 1;
    }
    if (!write_bin_to_current_dir(exe_data, exe_data_size, "unzip_tool.exe")) {
        DeleteFileA("unzip.dll"); // 清理已提取的DLL
        return 1;
    }

    // 2. 运行解压工具
    printf("\n开始解压文件...\n");
    int success = run_main_exe();

    // 3. 清理临时文件（保留用户的输出目录）
    printf("\n清理临时文件...\n");
    clean_temp_files();

    // 4. 输出结果
    if (success) {
        printf("\n=== 操作完成！ ===\n");
        printf("文件已解压到：%s\n", argv[2]);
        return 0;
    } else {
        fprintf(stderr, "\n=== 解压失败！ ===\n");
        return 1;
    }
}
